package com.castle.fortress.admin.flowable.form.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.castle.fortress.admin.flowable.form.dto.FlowableFormColDto;
import com.castle.fortress.admin.flowable.form.dto.FlowableFormConfigDto;
import com.castle.fortress.admin.flowable.form.entity.FlowableFormConfigEntity;
import com.castle.fortress.admin.flowable.form.mapper.FlowableFormConfigMapper;
import com.castle.fortress.admin.flowable.form.service.FlowableFormConfigService;
import com.castle.fortress.admin.form.dto.ColModelDto;
import com.castle.fortress.admin.form.dto.FormModelDto;
import com.castle.fortress.admin.utils.BizCommonUtil;
import com.castle.fortress.common.enums.YesNoEnum;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.BizErrorCode;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.utils.CommonUtil;
import com.castle.fortress.common.utils.ConvertUtil;
import lombok.extern.log4j.Log4j;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 表单配置管理 服务实现类
 *
 * @author castle
 * @since 2022-09-27
 */
@Service
@Log4j2
public class FlowableFormConfigServiceImpl extends ServiceImpl<FlowableFormConfigMapper, FlowableFormConfigEntity> implements FlowableFormConfigService {
    /**
    * 获取查询条件
    * @param flowableFormConfigDto
    * @return
    */
    public QueryWrapper<FlowableFormConfigEntity> getWrapper(FlowableFormConfigDto flowableFormConfigDto){
        QueryWrapper<FlowableFormConfigEntity> wrapper= new QueryWrapper();
        if(flowableFormConfigDto != null){
            FlowableFormConfigEntity flowableFormConfigEntity = ConvertUtil.transformObj(flowableFormConfigDto,FlowableFormConfigEntity.class);
            wrapper.like(StrUtil.isNotEmpty(flowableFormConfigEntity.getName()),"name",flowableFormConfigEntity.getName());
            wrapper.eq(flowableFormConfigEntity.getStatus() != null,"status",flowableFormConfigEntity.getStatus());
            wrapper.eq(flowableFormConfigEntity.getIsBind() != null,"is_bind",flowableFormConfigEntity.getIsBind());
            wrapper.orderByDesc("create_time");
        }
        return wrapper;
    }


    @Override
    public IPage<FlowableFormConfigDto> pageFlowableFormConfig(Page<FlowableFormConfigDto> page, FlowableFormConfigDto flowableFormConfigDto) {
        QueryWrapper<FlowableFormConfigEntity> wrapper = getWrapper(flowableFormConfigDto);
        Page<FlowableFormConfigEntity> pageEntity = new Page(page.getCurrent(), page.getSize());
        Page<FlowableFormConfigEntity> flowableFormConfigPage=baseMapper.selectPage(pageEntity,wrapper);
        Page<FlowableFormConfigDto> pageDto = new Page(flowableFormConfigPage.getCurrent(), flowableFormConfigPage.getSize(),flowableFormConfigPage.getTotal());
        pageDto.setRecords(ConvertUtil.transformObjList(flowableFormConfigPage.getRecords(),FlowableFormConfigDto.class));
        return pageDto;
    }

    @Override
    public IPage<FlowableFormConfigDto> pageFlowableFormConfigExtends(Page<FlowableFormConfigDto> page, FlowableFormConfigDto flowableFormConfigDto){
        Map<String,Long> pageMap = BizCommonUtil.getPageParam(page);
        FlowableFormConfigEntity flowableFormConfigEntity = ConvertUtil.transformObj(flowableFormConfigDto,FlowableFormConfigEntity.class);
        List<FlowableFormConfigEntity> flowableFormConfigList=baseMapper.extendsList(pageMap,flowableFormConfigEntity);
        Long total = baseMapper.extendsCount(flowableFormConfigEntity);
        Page<FlowableFormConfigDto> pageDto = new Page(page.getCurrent(), page.getSize(),total);
        pageDto.setRecords(ConvertUtil.transformObjList(flowableFormConfigList,FlowableFormConfigDto.class));
        return pageDto;
    }
    @Override
    public FlowableFormConfigDto getByIdExtends(Long id){
        FlowableFormConfigEntity  flowableFormConfigEntity = baseMapper.getByIdExtends(id);
        return ConvertUtil.transformObj(flowableFormConfigEntity,FlowableFormConfigDto.class);
    }

    @Override
    public List<FlowableFormConfigDto> listFlowableFormConfig(FlowableFormConfigDto flowableFormConfigDto){
        QueryWrapper<FlowableFormConfigEntity> wrapper = getWrapper(flowableFormConfigDto);
        List<FlowableFormConfigEntity> list = baseMapper.selectList(wrapper);
        return ConvertUtil.transformObjList(list,FlowableFormConfigDto.class);
    }

    @Override
    public FormModelDto convertToModel(FlowableFormConfigEntity formConfigEntity) {
        FormModelDto modelDto=new FormModelDto();
        if(CommonUtil.verifyParamNull(formConfigEntity,formConfigEntity.getId(),formConfigEntity.getTbContent())){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        List<ColModelDto> cols=new ArrayList<>();
        JSONArray jsonArray=new JSONArray(formConfigEntity.getTbContent());
        if(jsonArray.size()<1){
            throw new BizException(BizErrorCode.FORM_COL_EMPTY_ERROR);
        }
        modelDto.setTbName("castle_approve_form"+formConfigEntity.getId());
        String tag="",type="varchar(100)",label="";
        for(int i=0;i<jsonArray.size();i++){
            ColModelDto col=new ColModelDto();
            JSONObject o=jsonArray.getJSONObject(i);
            col.setColName(o.getStr("__vModel__"));
            tag=o.getJSONObject("__config__").getStr("tag");
            col.setColTag(tag);
            //分割组件不沉淀数据库
            if("el-divider".equals(tag)||"span".equals(tag)){
                continue;
            }
            col.setColType(convertTagToType(tag));
            label=o.getJSONObject("__config__").getStr("label");
            col.setColComment(label);
            cols.add(col);
            //省市区组件
            if("fortress-region".equals(tag)){
                ColModelDto colName=new ColModelDto();
                colName.setColName(col.getColName()+"Name");
                colName.setColType("varchar(150)");
                colName.setColComment(col.getColComment()+"名称描述");
                colName.setColTag("fortress-region-desc");
                cols.add(colName);
            }
        }
        //提交人相关字段
        ColModelDto applyUser=new ColModelDto();
        applyUser.setColName("_castle_apply_user");
        applyUser.setColType("varchar(255)");
        applyUser.setColComment("提交人");
        applyUser.setColTag("提交人");
        cols.add(applyUser);
        ColModelDto applyDate=new ColModelDto();
        applyDate.setColName("_castle_apply_date");
        applyDate.setColType("datetime");
        applyDate.setColComment("提交时间");
        applyDate.setColTag("提交时间");
        cols.add(applyDate);
        ColModelDto applyDept=new ColModelDto();
        applyDept.setColName("_castle_apply_dept");
        applyDept.setColType("varchar(255)");
        applyDept.setColComment("提交人所在部门");
        applyDept.setColTag("提交人所在部门");
        cols.add(applyDept);
        ColModelDto applyParentDepts=new ColModelDto();
        applyParentDepts.setColName("_castle_apply_dept_parents");
        applyParentDepts.setColType("text");
        applyParentDepts.setColComment("提交人所在部门上级部门");
        applyParentDepts.setColTag("提交人所在部门上级部门");
        cols.add(applyParentDepts);
        ColModelDto applyPostId=new ColModelDto();
        applyPostId.setColName("_castle_apply_post");
        applyPostId.setColType("varchar(255)");
        applyPostId.setColComment("提交人所处职位");
        applyPostId.setColTag("提交人所处职位");
        cols.add(applyPostId);
        //流程相关
        ColModelDto processId=new ColModelDto();
        processId.setColName("_castle_process_instance_id");
        processId.setColType("varchar(255)");
        processId.setColComment("流程实例");
        processId.setColTag("流程实例");
        cols.add(processId);
        ColModelDto engineVersion=new ColModelDto();
        engineVersion.setColName("_castle_process_engine_version");
        engineVersion.setColType("varchar(255)");
        engineVersion.setColComment("部署版本号");
        engineVersion.setColTag("部署版本号");
        cols.add(engineVersion);
        //审批字段
        ColModelDto approveStatus=new ColModelDto();
        approveStatus.setColName("_castle_approve_status");
        approveStatus.setColType("varchar(255)");
        approveStatus.setColComment("审批状态");
        approveStatus.setColTag("审批状态");
        cols.add(approveStatus);
        ColModelDto approveDate=new ColModelDto();
        approveDate.setColName("_castle_approve_date");
        approveDate.setColType("datetime");
        approveDate.setColComment("审批时间");
        approveDate.setColTag("审批时间");
        cols.add(approveDate);


        //请假相关字段
        if (YesNoEnum.YES.getCode().equals(formConfigEntity.getIsHoliday())){
            //请假类型
            ColModelDto leaveType=new ColModelDto();
            leaveType.setColName("_castle_leave_type");
            leaveType.setColType("varchar(64)");
            leaveType.setColComment("请假类型");
            leaveType.setColTag("请假类型");
            cols.add(leaveType);
            //请假开始时间
            ColModelDto startTime=new ColModelDto();
            startTime.setColName("_castle_start_time");
            startTime.setColType("varchar(64)");
            startTime.setColComment("请假开始时间");
            startTime.setColTag("请假开始时间");
            cols.add(startTime);
            //请假开始时间 (上午下午)
            ColModelDto startType=new ColModelDto();
            startType.setColName("_castle_start_type");
            startType.setColType("varchar(64)");
            startType.setColComment("请假开始时间(上午下午)");
            startType.setColTag("请假开始时间(上午下午)");
            cols.add(startType);
            //请假结束时间
            ColModelDto endTime=new ColModelDto();
            endTime.setColName("_castle_end_time");
            endTime.setColType("varchar(64)");
            endTime.setColComment("请假结束时间");
            endTime.setColTag("请假结束时间");
            cols.add(endTime);
            //请假结束时间 (上午下午)
            ColModelDto endType=new ColModelDto();
            endType.setColName("_castle_end_type");
            endType.setColType("varchar(64)");
            endType.setColComment("请假结束时间(上午下午)");
            endType.setColTag("请假结束时间(上午下午)");
            cols.add(endType);
            //请假总时长
            ColModelDto leaveDuration=new ColModelDto();
            leaveDuration.setColName("_castle_leave_duration");
            leaveDuration.setColType("varchar(255)");
            leaveDuration.setColComment("请假总时长");
            leaveDuration.setColTag("请假总时长");
            cols.add(leaveDuration);
        }
        modelDto.setCols(cols);
        return modelDto;
    }

    @Override
    public void updateBindStatus(Long id,Integer isBind) {
        if(!CommonUtil.verifyParamNull(id,isBind)){
            FlowableFormConfigEntity entity = new FlowableFormConfigEntity();
            entity.setId(id);
            entity.setIsBind(isBind);
            baseMapper.updateById(entity);
        }
    }

    @Override
    public Map<String, Map<String, String>> parseTbContentData(String tbContent) {
        Map<String, Map<String, String>> result = new HashMap<>();
        if(StrUtil.isNotEmpty(tbContent)){
            try {
                JSONArray content= new JSONArray(tbContent);
                for(int i=0;i<content.size();i++){
                    JSONObject obj = content.get(i,JSONObject.class);
                    Map<String, String> m = new HashMap<>();
                    m.put("colId",obj.getStr("__vModel__"));
                    m.put("colName",obj.getJSONObject("__config__").getStr("label"));
                    m.put("colType",convertTagToType(obj.getJSONObject("__config__").getStr("tag")));
                    result.put(m.get("colId"),m);
                }
            } catch (JSONException e) {
                return result;
            }
        }
        return result;
    }

    @Override
    public FlowableFormConfigDto getByFlowId(Long flowId) {
        FlowableFormConfigEntity entity = baseMapper.getByFlowId(flowId);
        return ConvertUtil.transformObj(entity,FlowableFormConfigDto.class);
    }

    @Override
    public List<FlowableFormColDto> getColsById(Long id) {
        FlowableFormConfigEntity entity = baseMapper.selectById(id);
        List<FlowableFormColDto> list = new ArrayList<>();
        if(entity!=null && StrUtil.isNotEmpty(entity.getDesignContent())){
            list = converToCol(entity.getDesignContent());
        }
        return list;
    }

    @Override
    public void removeByFlowableIds(List<Long> ids) {
        baseMapper.delByFlowableIds(ids);
    }

    @Override
    public void removeByAppIds(List<Long> ids) {
        baseMapper.delByAppIds(ids);
    }

    @Override
    public FlowableFormConfigEntity selByIdIgnoreDel(Serializable id) {
        return baseMapper.selByIdIgnoreDel(id);
    }

    private String convertTagToType(String tag){
        String type = "varchar(100)";
        switch (tag){
            case "el-input": type="varchar(100)";break;
            case "el-input-number": type="varchar(9)";break;
            case "tinymce": type="longtext";break;
            case "fortress-editor": type="longtext";break;
            case "el-select": type="varchar(100)";break;
            case "el-cascader": type="varchar(100)";break;
            case "el-radio-group": type="varchar(100)";break;
            case "el-checkbox-group": type="varchar(100)";break;
            case "el-switch": type="tinyint(1)";break;
            case "el-slider": type="varchar(100)";break;
            case "el-time-picker": type="varchar(20)";break;
            case "el-date-picker": type="varchar(50)";break;
            case "el-rate": type="varchar(2)";break;
            case "el-color-picker": type="varchar(16)";break;
            case "el-upload": type="text";break;
            case "image-upload": type="text";break;
            case "file-upload": type="text";break;
            case "video-upload": type="text";break;
            case "v-auditer": type="text";break;
            case "fortress-region":type = "varchar(100)";break;
            case "create_user":type = "bigint(64)";break;
            case "create_time":type = "datetime";break;
            case "fortress-holiday":type = "text";break;
        }
        return type;
    }

    /**
     * 将表单的模型设计数据转换为字段列表（只转换必填的字段）
     * @param designContent
     * @return
     */
    public List<FlowableFormColDto> converToCol(String designContent){
        List<FlowableFormColDto> list = new ArrayList<>();
        try {
            JSONArray array = new JSONArray(designContent);
            for(int i =0;i<array.size();i++){
                JSONObject obj = array.getJSONObject(i);
                JSONObject config = obj.getJSONObject("__config__");
                boolean valid = config.getBool("required");
                FlowableFormColDto colDto = new FlowableFormColDto();
                colDto.setLabel(config.getStr("label"));
                colDto.setTag(config.getStr("tag"));
                colDto.setVModel(obj.getStr("__vModel__"));
                colDto.setVData("");
                //单选 多选
                if("el-radio-group".equals(colDto.getTag()) || "el-checkbox-group".equals(colDto.getTag())){
                    JSONObject slot = obj.getJSONObject("__slot__");
                    if(slot!=null && slot.getJSONArray("options")!=null){
                        colDto.setVData(slot.getJSONArray("options").toString());
                    }
                }
                colDto.setValid(valid);
                list.add(colDto);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return list;
    }

}

